如何正确使用AnonFiles API来上传文件?

huangapple go评论186阅读模式
英文:

How to correctly use the AnonFiles API to post files?

问题

我正在尝试创建一个函数,使用anonfiles.com网站的anonfiles API来托管你的文件。尽管我正确使用了API,但它总是返回nil。Response is missing message

func host(file string) {
	fileBytes, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not read file,", err, "\033[0m")
		return
	}

	url := "https://api.anonfiles.com/upload"

	request, err := http.NewRequest("POST", url, bytes.NewBuffer(fileBytes))
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not post request,", err, "\033[0m")
		return
	}

	request.Header.Set("Content-Type", "application/octet-stream")

	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
		return
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
		return
	}

	var result map[string]interface{}
	err = json.Unmarshal(body, &result)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not parse response,", err, "\033[0m")
		return
	}

	if response.StatusCode == 200 {
		if result["url"] == nil {
			fmt.Println("\033[1;31mCommand > Host: Response is missing URL\033[0m")
			return
		}
		fmt.Println("文件托管成功:", result["url"].(string))
	} else {
		if result["message"] == nil {
			fmt.Println("\033[1;31mCommand > Host: Response is missing message\033[0m")
			return
		}
		fmt.Println("\033[1;31mCommand > Host:\033[0m", result["message"].(string))
	}
}
英文:

I am trying to make a function where it hosts your file on the anonfiles.com website using the anonfiles API. Even thought I am correctly using the api, it always returns nil. Response is missing message.

如何正确使用AnonFiles API来上传文件?

func host(file string) {
	fileBytes, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not read file,", err, "\033[0m")
		return
	}

	url := "https://api.anonfiles.com/upload"

	request, err := http.NewRequest("POST", url, bytes.NewBuffer(fileBytes))
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not post request,", err, "\033[0m")
		return
	}

	request.Header.Set("Content-Type", "application/octet-stream")

	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
		return
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
		return
	}

	var result map[string]interface{}
	err = json.Unmarshal(body, &result)
	if err != nil {
		fmt.Println("\033[1;31mCommand > Host: Could not parse response,", err, "\033[0m")
		return
	}

	if response.StatusCode == 200 {
		if result["url"] == nil {
			fmt.Println("\033[1;31mCommand > Host: Response is missing URL\033[0m")
			return
		}
		fmt.Println("File hosted successfully:", result["url"].(string))
	} else {
		if result["message"] == nil {
			fmt.Println("\033[1;31mCommand > Host: Response is missing message\033[0m")
			return
		}
		fmt.Println("\033[1;31mCommand > Host:\033[0m", result["message"].(string))
	}
}

答案1

得分: 0

我想花点时间将这些评论扩展成一个答案。

首先,正如我们之前讨论过的,你没有使用正确的API来上传文件。如果我们修改你的代码以显示完整的响应体,像这样:

client := &http.Client{}
response, err := client.Do(request)
if err != nil {
  fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
  return
}
defer response.Body.Close()

body, err := ioutil.ReadAll(response.Body)
if err != nil {
  fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
  return
}

fmt.Printf("BODY:\n%s\n", body)

我们会看到以下内容:

{
  "status": false,
  "error": {
    "message": "No file chosen.",
    "type": "ERROR_FILE_NOT_PROVIDED",
    "code": 10
  }
}

我们之所以得到这个错误,是因为你没有在multipart/form-data请求中提供file参数。我之前提供的链接中有几个发送多部分请求的示例;我测试了其中的一些示例,它们似乎按预期工作。


你对API返回的响应也有错误的假设。如果我们使用curl进行成功的请求并捕获响应的JSON,我们会发现它的结构如下:

{
  "status": true,
  "data": {
    "file": {
      "url": {
        "full": "https://anonfiles.com/k8cdobWey7/test_txt",
        "short": "https://anonfiles.com/k8cdobWey7"
      },
      "metadata": {
        "id": "k8cdobWey7",
        "name": "test.txt",
        "size": {
          "bytes": 12,
          "readable": "12 B"
        }
      }
    }
  }
}

请注意,没有response["url"]response["message"]。如果你想要上传文件的URL,你需要获取response["data"]["file"]["url"]["full"](或["short"])。

类似地,我们可以看到上面的错误响应示例,它的结构如下:

{
  "status": false,
  "error": {
    "message": "No file chosen.",
    "type": "ERROR_FILE_NOT_PROVIDED",
    "code": 10
  }
}

那不是result["message"],而是result["error"]["message"]

因为你将其反序列化为map[string]interface{},要获取这些嵌套键会有点麻烦。我发现最简单的方法是为上述响应创建Go结构体,并将其反序列化为相应类型的变量。

这样我得到了以下类型:

type (
  AnonFilesUrl struct {
    Full  string `json:"full"`
    Short string `json:"short"`
  }

  AnonFilesMetadata struct {
    ID   string `json:"id"`
    Name string `json:"name"`
    Size struct {
      Bytes    int    `json:"bytes"`
      Readable string `json:"readable"`
    } `json:"size"`
  }

  AnonFilesData struct {
    File struct {
      URL      AnonFilesUrl      `json:"url"`
      Metadata AnonFilesMetadata `json:"metadata"`
    } `json:"file"`
  }

  AnonFilesError struct {
    Message string
    Type    string
    Code    int
  }

  AnonFilesResponse struct {
    Status bool           `json:"status"`
    Data   AnonFilesData  `json:"data"`
    Error  AnonFilesError `json:"error"`
  }
)

然后,反序列化响应的代码如下:

var result AnonFilesResponse
err = json.Unmarshal(body, &result)

我们可以获取如下字段:

fmt.Printf("URL: %s\n", result.Data.File.URL.Full)
英文:

I'd thought I'd take a moment to expand those comments into an answer.

First, as we we've already discussed, you're not using the correct API to upload files. If we modify your code to show the complete response body, like this:

client := &http.Client{}
response, err := client.Do(request)
if err != nil {
fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
return
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
return
}
fmt.Printf("BODY:\n%s\n", body)

We see the following:

{
"status": false,
"error": {
"message": "No file chosen.",
"type": "ERROR_FILE_NOT_PROVIDED",
"code": 10
}
}

We're getting this error because you're not providing the file parameter in a multipart/form-data request. The post to which I linked earlier has several examples of sending a multipart request; I've tested a couple of them and they seem to work as expected.


You're also making incorrect assumptions about the response returned by the API. If we make a successful request using curl and capture the response JSON, we find that it looks like this:

{
"status": true,
"data": {
"file": {
"url": {
"full": "https://anonfiles.com/k8cdobWey7/test_txt",
"short": "https://anonfiles.com/k8cdobWey7"
},
"metadata": {
"id": "k8cdobWey7",
"name": "test.txt",
"size": {
"bytes": 12,
"readable": "12 B"
}
}
}
}
}

Note that there is no response["url"] or response["message"]. If you want the URL for the uploaded file, you need to get response["data"]["file"]["url"]["full"] (or ["short"]).

Similarly, we can see examples of the error response above, which looks like this:

{
"status": false,
"error": {
"message": "No file chosen.",
"type": "ERROR_FILE_NOT_PROVIDED",
"code": 10
}
}

That's not result["message"]; that's result["error"]["message"].

Because you're unmarshalling into a map[string]interface, getting at these nested keys is going to be a bit of a pain. I found it easiest to create Go structs for the above responses, and just unmarshal into an appropriately typed variable.

That gets me the following types:

type (
AnonFilesUrl struct {
Full  string `json:"full"`
Short string `json:"short"`
}
AnonFilesMetadata struct {
ID   string `json:"id"`
Name string `json:"name"`
Size struct {
Bytes    int    `json:"bytes"`
Readable string `json:"readable"`
} `json:"size"`
}
AnonFilesData struct {
File struct {
URL      AnonFilesUrl      `json:"url"`
Metadata AnonFilesMetadata `json:"metadata"`
} `json:"file"`
}
AnonFilesError struct {
Message string
Type    string
Code    int
}
AnonFilesResponse struct {
Status bool           `json:"status"`
Data   AnonFilesData  `json:"data"`
Error  AnonFilesError `json:"error"`
}
)

And then unmarshalling the response looks like:

var result AnonFilesResponse
err = json.Unmarshal(body, &result)

And we can ask for fields like:

fmt.Printf("URL: %s\n", result.Data.File.URL.Full)

huangapple
  • 本文由 发表于 2023年2月5日 19:56:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75352042.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定