source

REST 웹 서비스를 사용하여 메타데이터가 포함된 파일을 업로드하려면 어떻게 해야 합니까?

gigabyte 2023. 2. 10. 22:01
반응형

REST 웹 서비스를 사용하여 메타데이터가 포함된 파일을 업로드하려면 어떻게 해야 합니까?

현재 다음 URL을 제공하는 REST 웹 서비스가 있습니다.

http://서버/데이터/미디어

서, 는 「」를 사용할 수 있습니다.POST JSONada JSON:

{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873
}

새 미디어 메타데이터를 작성하기 위해 사용합니다.

이제 미디어 메타데이터와 동시에 파일을 업로드할 수 있는 기능이 필요합니다.떻게게 하면 ?? ???나는 새로운 부동산에 대해 소개 할 수 있습니다.file더 생각하고 있습니다.base64 에 、 더만 、 더 and 、 and and 、 and and 、 and and 、 and and 、 and and 、 and and and and and and 。

'어느 때 보다'라는 말도 multipart/form-dataHTML 폼으로 전송되는 것 같은 것이 있습니다만, 저는 REST Web 서비스를 사용하고 있기 때문에 가능하면 JSON을 계속 사용하고 싶습니다.

2단계 접근 방식이 합리적인 해결책이라는 Greg의 의견에 동의하지만, 저는 그 반대로 하겠습니다.저는 다음과 같이 하겠습니다.

POST http://server/data/media
body:
{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873
}

메타데이터 엔트리를 작성하고 다음과 같은 응답을 반환하려면:

201 Created
Location: http://server/data/media/21323
{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873,
    "ContentUrl": "http://server/data/media/21323/content"
}

클라이언트는 이 ContentUrl을 사용하여 파일 데이터로 PUT을 수행할 수 있습니다.

이 접근방식의 장점은 대량의 데이터로 인해 서버가 과부하가 걸리기 시작하면 반환되는 URL은 더 많은 공간/용량을 가진 다른 서버를 가리킬 수 있다는 것입니다.또는 대역폭이 문제가 되는 경우에는 일종의 라운드로빈 어프로치를 실장할 수도 있습니다.

JSON을 하는 것은 multipart/form-dataJSON:

curl -F "metadata=<metadata.json" -F "file=@my-file.tar.gz" http://example.com/add-file

서버측:

class AddFileResource(Resource):
    def render_POST(self, request):
        metadata = json.loads(request.args['metadata'][0])
        file_body = request.args['file'][0]
        ...

여러 파일을 업로드하려면 각 파일에 대해 별도의 "양식 필드"를 사용할 수 있습니다.

curl -F "metadata=<metadata.json" -F "file1=@some-file.tar.gz" -F "file2=@some-other-file.tar.gz" http://example.com/add-file

서버 에는 다음과 같은 상태가 .이 경우 서버 코드는request.args['file1'][0] ★★★★★★★★★★★★★★★★★」request.args['file2'][0]

또는 같은 것을 많은 경우에 재사용할 수 있습니다.

curl -F "metadata=<metadata.json" -F "files=@some-file.tar.gz" -F "files=@some-other-file.tar.gz" http://example.com/add-file

...이 경우request.args['files']2번으로 하다

또는 단일 필드를 통해 여러 파일을 전달합니다.

curl -F "metadata=<metadata.json" -F "files=@some-file.tar.gz,some-other-file.tar.gz" http://example.com/add-file

...이 경우request.args['files']모든 파일을 포함하는 문자열이 됩니다.이 문자열은 사용자가 직접 해석해야 합니다.어떻게 해석하는지는 모르겠지만 어렵지 않을 것입니다.또는 이전 접근 방식을 사용하는 것이 좋습니다.

「 」의 @ ★★★★★★★★★★★★★★★★★」<라는 것이다.@, 「파일 업로드」는 「파일 업 로드」로 첨부합니다.<이치노

추신. 단지 내가 이걸 사용한다고 해서curl「」의 POSTPython과 같은 프로그래밍 언어나 충분한 기능을 가진 도구를 사용하여 동일한 HTTP 요청을 전송할 수 없다는 것을 의미하지는 않습니다.

이 문제에 접근하는 방법 중 하나는 업로드를 2단계 프로세스로 만드는 것입니다.먼저 POST를 사용하여 파일 자체를 업로드합니다.이 경우 서버는 클라이언트에 ID를 반환합니다(ID는 파일콘텐츠의 SHA1일 수 있습니다).그런 다음 두 번째 요청은 메타데이터를 파일 데이터와 관련짓습니다.

{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873,
    "ContentID": "7a788f56fa49ae0ba5ebde780efe4d6a89b5db47"
}

JSON 요청에 인코딩된 파일 데이터베이스 64를 포함하면 전송되는 데이터의 크기가 33% 증가합니다.이것은 파일의 전체 크기에 따라 중요하거나 중요하지 않을 수 있습니다.

또 다른 접근법은 원시 파일 데이터의 POST를 사용하지만 HTTP 요청 헤더에 메타데이터를 포함하는 것입니다.다만, 이것은 기본적인 REST 조작을 약간 벗어난 것으로, HTTP 클라이언트라이브러리에 따라서는, 보다 곤란한 경우가 있습니다.

왜 8년 동안 아무도 쉬운 답을 올리지 않았는지 이해할 수 없다.파일을 base64로 인코딩하지 않고 json을 문자열로 인코딩합니다.그럼 서버 측에서 json을 디코딩하면 됩니다.

Javascript의 경우:

let formData = new FormData();
formData.append("file", myfile);
formData.append("myjson", JSON.stringify(myJsonObject));

Content-Type: multipart/form-data를 사용하여 게시합니다.

서버측에서 파일을 정상적으로 취득하고 json을 문자열로 취득합니다.문자열을 개체로 변환합니다. 개체는 일반적으로 사용하는 프로그래밍 언어에 관계없이 한 줄의 코드입니다.

(네, 잘 동작합니다.내 앱 중 하나에서 실행 중).

매우 오래된 질문인 것은 알지만, 제가 같은 질문을 찾으면서 이 게시물을 보게 되었기 때문에 다른 사람에게 도움이 되었으면 합니다.비슷한 문제가 있었습니다만, 제 메타데이터는 GUID와 int였습니다.하지만 해결책은 같다.필요한 메타데이터를 URL의 일부로 만들 수 있습니다.

"Controller" 클래스의 POST 수락 방법:

public Task<HttpResponseMessage> PostFile(string name, float latitude, float longitude)
{
    //See http://stackoverflow.com/a/10327789/431906 for how to accept a file
    return null;
}

등록하는 루트에 관계없이 WebApiConfig.이 경우는, 등록(Http Configuration)해 주세요.

config.Routes.MapHttpRoute(
    name: "FooController",
    routeTemplate: "api/{controller}/{name}/{latitude}/{longitude}",
    defaults: new { }
);

파일과 메타데이터가 하나의 리소스를 생성하는 경우 두 리소스를 모두 하나의 요청으로 업로드하는 것이 좋습니다.요청 예는 다음과 같습니다.

POST https://target.com/myresources/resourcename HTTP/1.1

Accept: application/json

Content-Type: multipart/form-data; 

boundary=-----------------------------28947758029299

Host: target.com

-------------------------------28947758029299

Content-Disposition: form-data; name="application/json"

{"markers": [
        {
            "point":new GLatLng(40.266044,-74.718479), 
            "homeTeam":"Lawrence Library",
            "awayTeam":"LUGip",
            "markerImage":"images/red.png",
            "information": "Linux users group meets second Wednesday of each month.",
            "fixture":"Wednesday 7pm",
            "capacity":"",
            "previousScore":""
        },
        {
            "point":new GLatLng(40.211600,-74.695702),
            "homeTeam":"Hamilton Library",
            "awayTeam":"LUGip HW SIG",
            "markerImage":"images/white.png",
            "information": "Linux users can meet the first Tuesday of the month to work out harward and configuration issues.",
            "fixture":"Tuesday 7pm",
            "capacity":"",
            "tv":""
        },
        {
            "point":new GLatLng(40.294535,-74.682012),
            "homeTeam":"Applebees",
            "awayTeam":"After LUPip Mtg Spot",
            "markerImage":"images/newcastle.png",
            "information": "Some of us go there after the main LUGip meeting, drink brews, and talk.",
            "fixture":"Wednesday whenever",
            "capacity":"2 to 4 pints",
            "tv":""
        },
] }

-------------------------------28947758029299

Content-Disposition: form-data; name="name"; filename="myfilename.pdf"

Content-Type: application/octet-stream

%PDF-1.4
%
2 0 obj
<</Length 57/Filter/FlateDecode>>stream
x+r
26S00SI2P0Qn
F
!i\
)%!Y0i@.k
[
endstream
endobj
4 0 obj
<</Type/Page/MediaBox[0 0 595 842]/Resources<</Font<</F1 1 0 R>>>>/Contents 2 0 R/Parent 3 0 R>>
endobj
1 0 obj
<</Type/Font/Subtype/Type1/BaseFont/Helvetica/Encoding/WinAnsiEncoding>>
endobj
3 0 obj
<</Type/Pages/Count 1/Kids[4 0 R]>>
endobj
5 0 obj
<</Type/Catalog/Pages 3 0 R>>
endobj
6 0 obj
<</Producer(iTextSharp 5.5.11 2000-2017 iText Group NV \(AGPL-version\))/CreationDate(D:20170630120636+02'00')/ModDate(D:20170630120636+02'00')>>
endobj
xref
0 7
0000000000 65535 f 
0000000250 00000 n 
0000000015 00000 n 
0000000338 00000 n 
0000000138 00000 n 
0000000389 00000 n 
0000000434 00000 n 
trailer
<</Size 7/Root 5 0 R/Info 6 0 R/ID [<c7c34272c2e618698de73f4e1a65a1b5><c7c34272c2e618698de73f4e1a65a1b5>]>>
%iText-5.5.11
startxref
597
%%EOF

-------------------------------28947758029299--

superagent / express / multer를 사용하는 경우 ccleve의 답변을 기반으로 다음과 같은 방법으로 프런트 엔드에서 멀티파트 요청을 작성합니다.

superagent
    .post(url)
    .accept('application/json')
    .field('myVeryRelevantJsonData', JSON.stringify({ peep: 'Peep Peep!!!' }))
    .attach('myFile', file);

cf https://visionmedia.github.io/superagent/ #syslogart-syslog.

급행열차에서, 무엇이든지 간에,field다음 작업을 수행한 후 요구 보디가 됩니다.

app.use(express.json({ limit: '3MB' }));

경로에는 다음과 같은 것이 포함됩니다.

const multerMemStorage = multer.memoryStorage();
const multerUploadToMem = multer({
  storage: multerMemStorage,
  // Also specify fileFilter, limits...
});

router.post('/myUploads',
  multerUploadToMem.single('myFile'),
  async (req, res, next) => {
    // Find back myVeryRelevantJsonData :
    logger.verbose(`Uploaded req.body=${JSON.stringify(req.body)}`);

    // If your file is text:
    const newFileText = req.file.buffer.toString();
    logger.verbose(`Uploaded text=${newFileText}`);
    return next();
  },
  ...

다만, 디스크 스토리지에 관해서, multer doc의 메모는 다음과 같습니다.

req.body가 아직 완전히 채워지지 않았을 수 있습니다.이것은 클라이언트가 필드와 파일을 서버로 전송하는 순서에 따라 달라집니다.

예를 들어 파일을 따라 전달된 json 메타데이터를 기반으로 타깃 dir/filename을 계산하는 것은 신뢰할 수 없다는 것을 의미합니다.

언급URL : https://stackoverflow.com/questions/3938569/how-do-i-upload-a-file-with-metadata-using-a-rest-web-service

반응형