如何使用XMLHttpRequest和FormData对象在multipart / form-data上设置自己的边界

时间:2013-02-07 05:38:36

标签: xmlhttprequest multipartform-data boundary

在使用FormData对象将文件附加到请求时,我一直在尝试找到一种在XMLHttpRequest对象上设置自己边界的方法。我已经看过很多帖子,每个人都说“只是不设置边界,它会自动为你生成。”这不是我想要的。让我解释一下我需要什么,所以我没有得到这些回应。

我有一个Web服务端点,我发送了一个包含两个图像和一些json数据的multipart / form-data请求。由于WCF没有任何方法来解析多部分请求,我使用一些开源代码构建了自己的解析器。它的工作方式是,我定义了一个边界,用于分隔请求的每个部分,并从那里一切工作hunky dory。因此,我必须能够将边界设置为服务器代码所期望的,以便我的解析类能够在输入流中找到任何内容。

我知道这可以做到,因为我已经使用Fiddler这样做了,并且同事可以在我们正在构建的应用程序中调用我的方法,但我正在尝试使用Chrome浏览器应用程序名为Postman,使用FormData对象发送多部分请求。除了请求生成它们自己的边界之外,它的工作原理是:

----WebKitFormBoundaryQUWQnB6c7TzNzdcz

末尾的附加字符串是随机生成的,因此它永远不会相同,因此我无法使用此工具测试我的端点,因为服务器无法知道要查找的边界。

我尝试在其中设置带有边界的Content-Type标头,当请求显示添加到请求的标头时,主体仍然使用随机边界。

所以问题是如何告诉FormData对象和/或XMLHttpRequest对象使用我的边界而不是生成的随机边界?

我无法想象这是一件不寻常的事情,我的意思是到现在为止我所有使用multipart / form-data调用服务的经验告诉我在api中设置边界是什么并且没有人说过“只是不设置它,我们将使用生成的随机垃圾......”

同样作为视觉,这是我在标题中看到的内容:

Request Headers
POST /DHICachet.svc/json/DepositCheck HTTP/1.1
Host: dhiibews.securexfr.com
Connection: keep-alive
Content-Length: 514696
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11
Content-Type: multipart/form-data; boundary=myboundary
Cache-Control: no-cache
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: ASP.NET_SessionId=zdepe2nhkz0vbhxiulzc2qq1

Request Payload
------WebKitFormBoundaryQUWQnB6c7TzNzdcz
Content-Disposition: form-data; name="item"; filename="Screen shot 2012-09-03 at 4.00.10 AM.png"
Content-Type: image/png


------WebKitFormBoundaryQUWQnB6c7TzNzdcz--

请注意,即使我的边界在请求标头中设置为myboundary,主体也会放置在幕后生成的任何边界。另请注意,如果我没有设置该标头,则只需将其放入在其中随机边界。

3 个答案:

答案 0 :(得分:1)

这并没有真正回答我的问题,但我确实找到了解决方法。我突然意识到,我可以通过在内容类型标题上进行一些字符串数学来检测通过的边界。我刚刚在代码中添加了以下内容:

string contenttype = _ctx.IncomingRequest.Headers["Content-Type"].ToString();
string boundary = contenttype.Substring(contenttype.IndexOf('=') + 1);

这允许我接受任何边界进行调试。然而,我仍然需要我们特定的生产边界。

答案 1 :(得分:0)

我遇到了类似的问题,在发布帖子时,我将内容类型标题设置为undefined ... 'Content-Type': undefined

我相信浏览器会自动正确处理FormData的POST并为您预期设置Content-type标头,包括未设置的边界。所以这意味着服务器上不需要特殊的请求头解析逻辑。

答案 2 :(得分:0)

您可以将文件转换为二进制字符串,然后提交。代码是 TypeScript,但 JavaScript 类似。

async uploadFile(myFile: File): Promise<boolean> {
        // Get the binary string from the file in order to send the file with `multipart/form-data`
        const contentPromise = new Promise<string>((resolve) => {
            const reader = new FileReader()
            reader.onload = async function (evt) {
                const pdfContent: string = evt?.target?.result as string
                resolve(pdfContent)
            }

            reader.readAsBinaryString(myFile)
        })
        const binaryContent = await contentPromise

        // Send the request
        const path = `api/update-file`
        const content = `--WebAppBoundary
Content-Disposition: form-data; name="myFile"; filename="${myFile.name}"
Content-Type: application/pdf

${binaryContent}
--WebAppBoundary--`

        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'multipart/form-data; boundary=WebAppBoundary'
            },
            body: content
        }

        const response: { code: number; message: string } = await (await fetch(path, requestOptions)).json()

        // Return the response
        return response.code === 200
    }